#define SOUND_ALSA      0
#define SOUND_OSS       1

#if SOUND_ALSA
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#endif

#if SOUND_OSS
#include <fcntl.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <sys/soundcard.h>
#endif

#include <stdio.h>
#include <speex/speex.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BIND_PORT 12345   //接收音频数据端口
//#define TO_ADDR "192.168.2.233"

/*The frame size in hardcoded for this sample code but it doesn't have to be*/
#define FRAME_SIZE 160

struct sockaddr_in addr;
int fd;
socklen_t len;

/*Holds the audio that will be written to file (16 bits per sample)*/
short out[FRAME_SIZE];
/*Speex handle samples as float, so we need an array of floats*/
float output[FRAME_SIZE];
char cbits[200];
int nbBytes;
/*Holds the state of the decoder*/
void *state;
/*Holds bits so they can be read and written to by the Speex routines*/
SpeexBits bits;
int i, tmp;

#define SK8850       0

#if SK8850
#define _MODIFY_MIXER  //20100211
#endif


#if SK8850
void mixer_init(void);
#endif


#if SOUND_OSS
#define AUDIODSP  1
#define AUDIODSP1 2
#define DEVICE_NAME "/dev/dsp"
#define MIXER_DEVICE	"/dev/mixer"
int audio_fd;
int devrecfd = 0;
int devplayfd = 0;
int mixer_fd = 0;
int abuf_size;
#define AUDIODSP  1
#define AUDIODSP1 2

#define FMT8BITS 8 
#define FMT16BITS 16

#define FMT8K 8000
#define FMT16K 16000
#define FMT22K 22000
#define FMT44K 44000

#define MONO 0
#define STERO 1

#define AUDIORECBLK  512
#define AUDIOPLAYBLK  512

#define AUDIOBLK (128*6)   //每帧48ms
#endif



#if SK8850
void InitDefence()
{
}

void Uninit_Ir_Deal()
{
}

void CheckDefence()
{
}

int GetisHost(void)  //供lib调用　
{
	return 1;
}

void SetWB_Ir_Support(int WB_Ir_Support)   //WB 是否支持通过串口发送 IO 口状态
{
  
}

void Init_Ir_Deal()
{
}

//---------------------------------------------------------------------------
#ifdef _MODIFY_MIXER
void mixer_init(void)
{
#if 1
  if(mixer_fd > 0)
   {
    close(mixer_fd);
    mixer_fd = 0;
   }
  /* Open Mixer device */
  if ((mixer_fd = open(MIXER_DEVICE, O_RDONLY)) > 0)
   {
    //int enable = 1;
    //ioctl(mixer_fd, MIXER_WRITE(SOUND_ONOFF_MIN), &enable);
    int enablemute = 1;
    ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_PCM), &enablemute);      //SOUND_MIXER_SPEAKER
    enablemute = 1;
    ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_MIC), &enablemute);
   }
  else
   {
    printf("mix_fd open fail\n");
   }
  if(mixer_fd > 0)
   {
    close(mixer_fd);
    mixer_fd = 0;
   }
#endif
}
#endif



int SpkVolume[5] = {60, 70, 80, 90, 100};
void SoundSetSpeakerVolume(unsigned char volume)
{
#if 1
  int vol, sys_vol, devs;
  if(mixer_fd > 0)
   {
    close(mixer_fd);
    mixer_fd = 0;
   }
  if(volume > 4)
    printf("SoundSetSpeakerVolume  volume = %d\n", volume);
  /* Open Mixer device */
  if ((mixer_fd = open(MIXER_DEVICE, O_RDONLY)) > 0)
   {
    ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devs);
    printf("SoundSetSpeakerVolume devs = 0x%X, SOUND_MIXER_PCM = 0x%X, SOUND_ONOFF_MIN = 0x%X, SOUND_MIXER_SPEAKER = 0x%X\n",
            devs, SOUND_MIXER_PCM, SOUND_ONOFF_MIN, SOUND_MIXER_SPEAKER);
    if (devs & (1 << SOUND_MIXER_PCM))
     {
      sys_vol = SpkVolume[volume];
      vol = (((unsigned short)sys_vol) << 8) | sys_vol;
      printf("write speaker vol = %d\n", vol);
      ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_PCM), &vol);

      //ioctl(mixer_fd, MIXER_READ(SOUND_MIXER_PCM), &vol);
      //printf("read speaker vol = %d\n", vol);
     }
   }
  else
    printf("mixer_fd = %d\n", mixer_fd);
  if(mixer_fd > 0)
   {
    close(mixer_fd);
    mixer_fd = 0;
   }
#endif
}

#endif

/*
udp接收端初始化
*/   
void init_udp()
{
	printf("init_udp 1111111111111111111\n");
	/* create what looks like an ordinary UDP socket */
	if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) 
	{
		perror("socket");
		exit(1);
	}
	printf("init_udp 3333333\n");
	/* set up destination address */
	memset(&addr,0,sizeof(addr));
	printf("init_udp 44444444\n");     
	addr.sin_family=AF_INET;
	addr.sin_addr.s_addr=htonl(INADDR_ANY);
	addr.sin_port=htons(BIND_PORT);
	printf("init_udp 5555555\n");
	
	if(bind ( fd, (struct sockaddr *)&addr, sizeof(addr))==-1)
		printf("error\n");
	else
		printf("ok\n");    
	printf("init_udp 999999999\n");
	len =  sizeof(addr);
}


#if SOUND_OSS
//---------------------------------------------------------------------------
/*
* Open Sound device
* Return 1 if success, else return 0.
*/
int OpenSnd(/* add by new version */int nWhich)
{
  int status;   // 系统调用的返回值
  int setting;
  if(nWhich == 1)
   {
     printf("open devrecfd = %d\n", devrecfd);
     if(devrecfd > 0)
      {
       close(devrecfd);
      }
     devrecfd = 0;
     if(devrecfd == 0)
      {
       devrecfd = open ("/dev/dsp", O_RDONLY);//, 0);//open("/dev/dsp", O_RDWR);
       if(devrecfd < 0)
        {
         devrecfd = 0;
         return 0;
        }
       #if 1
       //#ifdef _AUDIO_BUF_48MS
       // setting = 0x0010000A;//0x00040009;//0x0008000B;//0x0002000C;//0x0004000A;//0x0008000B;//0x00040009;
       //#else
        setting = 0x00100007;//0x00040009;//0x0008000B;//0x0002000C;//0x0004000A;//0x0008000B;//0x00040009;
       //#endif
       status = ioctl(devrecfd, SNDCTL_DSP_SETFRAGMENT, (char *)&setting);
       if (status == -1) {
         perror("ioctl buffer size");
         return -1;
        }
       #endif
      }
/*    // Open Mixer device
    if((mixer_fd = open(MIXER_DEVICE, O_RDONLY, 0)) != -1)
     {
      int enable = 1;
      ioctl(mixer_fd, MIXER_WRITE(SOUND_ONOFF_MIN), &enable);
      int enablemute = 1;
      ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_SPEAKER), &enablemute);
     }
    else
     {
      P_Debug("mix_fd open fail\n");
     }   */   
    }
  else
   {
     printf("open devplayfd = %d\n", devplayfd);
     if(devplayfd > 0)
      {
       close(devplayfd);
      }
     devplayfd = 0;
     if(devplayfd == 0)
      {
       devplayfd = open ("/dev/dsp1", O_WRONLY);//, 0);//open("/dev/dsp", O_RDWR);
       if(devplayfd < 0)
        {
         devplayfd = 0;
         return 0;
        }
       #if 1
       //#ifdef _AUDIO_BUF_48MS
       // setting = 0x0010000A;//0x00040009;//0x0008000B;//0x0002000C;//0x0004000A;//0x0008000B;//0x00040009;
       //#else
        setting = 0x00100007;//0x00100007;//0x0004000A;//0x0004000A;//0x0008000B;//0x00040009;   0x0002000C;  0x00040008
       //#endif
       status = ioctl(devplayfd, SNDCTL_DSP_SETFRAGMENT, (char *)&setting);
       if (status == -1) {
         perror("ioctl buffer size");
         return -1;
        }
       #endif
      }
     #ifdef _MODIFY_MIXER
       mixer_init();
     #else
      if(mixer_fd > 0)
       {
        close(mixer_fd);
        mixer_fd = 0;
       }
     /* Open Mixer device */
     if((mixer_fd = open(MIXER_DEVICE, O_RDONLY, 0)) != -1)     // O_RDONLY    O_WRONLY
      {
       int enable = 1;
       ioctl(mixer_fd, MIXER_WRITE(SOUND_ONOFF_MIN), &enable);
       int enablemute = 1;
       ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_SPEAKER), &enablemute);
      }
     else
      {
       perror("mix_fd open fail\n");
      }
    #endif 
    
    #if SK8850
    SoundSetSpeakerVolume(4); //设置音量
    //SoundSetMicVolume(LocalCfg.MicVolume);//LocalCfg.SpkVolume); //设置MIC音量     
    #endif
   }

  return 1;
}

//---------------------------------------------------------------------------
/*
* Set Record an Playback format
* return 1 if success, else return 0.
* bits -- FMT8BITS(8bits), FMT16BITS(16bits)
* hz -- FMT8K(8000HZ), FMT16K(16000HZ), FMT22K(22000HZ), FMT44K(44000HZ)
  chn -- MONO 1 STERO 2
*/
int SetFormat(int nWhich, int bits, int hz, int chn)
{
  int samplesize;
  int tmp;
  int dsp_stereo;
  int setting;

  int arg;	// 用于ioctl调用的参数
  int status;   // 系统调用的返回值
  int devfd;
  if(nWhich == AUDIODSP)
    devfd = devrecfd;
  else
    devfd = devplayfd;

  if(devfd <= 0)
   {
    perror("devfd small than 0\n");
    return -1;
   }

//  if(nWhich == AUDIODSP)
//   {
//    P_Debug("SetFormat 1\n");
//    usleep(1000*1000);
    // 设置采样时的量化位数       FIC8120只支持16位
    status = ioctl(devfd, SOUND_PCM_READ_BITS, &arg);
    if(arg != bits)
     {
      arg = bits;
      status = ioctl(devfd, SOUND_PCM_WRITE_BITS, &arg);
      if (status == -1)
       {
        perror("SOUND_PCM_WRITE_BITS ioctl failed\n");
        //ResetMachine();
       }
      if (arg != bits)
        perror("unable to set sample size\n");
     }
//    P_Debug("SetFormat 2\n");
//    usleep(1000*1000);
  // 设置采样时的声道数目
  status = ioctl(devfd, SOUND_PCM_READ_CHANNELS, &arg);
  if(arg != chn)
   {
    arg = chn;
    status = ioctl(devfd, SOUND_PCM_WRITE_CHANNELS, &arg);
    if (status == -1)
     {
      perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
     }
    if (arg != chn)
      perror("unable to set number of channels");
   }
  //printf("SetFormat 3\n");
  // 设置采样时的采样频率
  status = ioctl(devfd, SOUND_PCM_READ_RATE, &arg);
  if(arg != hz)
   {
    arg = hz;
    status = ioctl(devfd, SOUND_PCM_WRITE_RATE, &arg);
    if (status == -1)
     {
      perror("SOUND_PCM_WRITE_RATE ioctl failed");
     }
   }
  //printf("SetFormat 4\n");
  abuf_size = AUDIOBLK;
/*  if(nWhich == AUDIODSP)
   {
       setting = 0x00040009;//0x000F0009;
       status = ioctl(devfd, SNDCTL_DSP_SETFRAGMENT, &setting);
       if (status == -1) {
           perror("ioctl buffer size");
           return -1;
        }
   }    */

  ioctl(devfd, SNDCTL_DSP_GETBLKSIZE, &abuf_size);
  #ifdef _DEBUG
    printf("abuf_size= %d\n",abuf_size);
  #endif  
  if (abuf_size < 4 || abuf_size > 65536)
  {
 //   if (abuf_size == -1)
      printf ( "Invalid audio buffers size %d\n", nWhich);
  }


//ioctl(devfd, SOUND_MIXER_READ(SOUND_MIXER_MIC), &vol);
//printf("Mic gain is at %d %%\n", vol);


//  arg=0;
//  ioctl(devfd, SNDCTL_DSP_NONBLOCK,(char   *)&arg);


/*  tmp = bits;
  if( -1 == ioctl(devfd, SNDCTL_DSP_SETFMT, &tmp))
   {
     printf("Set fmt to s16_little faile%d\n", nWhich);
    return 0;
   }        */

/*  tmp = hz;
  printf("SNDCTL_DSP_SPEED1= %d\n",tmp);
  if( -1 == ioctl(devrecfd, SNDCTL_DSP_SPEED, &tmp))
   {
    printf("Set speed to %d:%d\\n", hz, nWhich);
    return 0;
   }
  printf("SNDCTL_DSP_SPEED= %d\n",tmp);

  samplesize = bits;
  tmp = bits;
  ioctl(devrecfd, SNDCTL_DSP_SAMPLESIZE, &tmp);
  if (tmp != samplesize)
  {
  	printf( "Unable to set the sample size\n");
  }
  printf("SNDCTL_DSP_SAMPLESIZE= %d\n",tmp);

  tmp = chn;
  if(-1 == ioctl(devrecfd, SNDCTL_DSP_STEREO, &tmp))
   {
    P_Debug("Set Audio Channel fail\n");
    return 0;
   }
  P_Debug("Set Audio Channel success\n");      */

/*  dsp_stereo =chn;
  if (ioctl (devfd, SNDCTL_DSP_STEREO, &dsp_stereo)==-1)
  {
      P_Debug ( "unable to set mono/stereo\n");
  }
  P_Debug("set mono/stereo success\n");      */


  return 1;
}
#endif

/*
程序入口
*/
int main() 
{ 
    #if SK8850
    int WB_Ir_Support = 0;
    #define WB_Version  "20100101"
    #endif
    
	long loops; 
	int rc; 
	int size; 
	#if SOUND_ALSA
	snd_pcm_t *handle; 
	snd_pcm_hw_params_t *params; 
	snd_pcm_uframes_t frames; 
	#endif	
	unsigned int val; 
	int dir; 
	char *buffer; 
 
	printf("1111111111111111111\n");
	init_udp();

	#if SK8850
	//Init_Usb_Wb(&WB_Ir_Support, WB_Version);//初始化 libusb
	WbSet1463Volume(0x30);
	#endif
	
   /*Create a new decoder state in narrowband mode*/
   state = speex_decoder_init(&speex_nb_mode);

   /*Set the perceptual enhancement on*/
   tmp=1;
   speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp);
   
   /*Initialization of the structure that holds the bits*/
   speex_bits_init(&bits);
       
	#if SOUND_ALSA
	printf("%s: 222222222222\n", __FUNCTION__);
	/* Open PCM device for playback. */
	rc=snd_pcm_open(&handle,"default", SND_PCM_STREAM_PLAYBACK, 0);
 	if (rc< 0) 
 	{ 
 		fprintf(stderr,  "unable to open pcm device: %s\n",    snd_strerror(rc));
   		exit(1); 
	} 
	printf("%s: 33333333333\n", __FUNCTION__);
	/* Allocate a hardware parameters object. */
	snd_pcm_hw_params_alloca(&params); 
	/* Fill it in with default values. */
	snd_pcm_hw_params_any(handle, params);
	/* Set the desired hardware parameters. */ 
	/* Interleaved mode */ 
	snd_pcm_hw_params_set_access(handle,params, SND_PCM_ACCESS_RW_INTERLEAVED); 
	/* Signed 16-bit little-endian format */ 
	snd_pcm_hw_params_set_format(handle,params, SND_PCM_FORMAT_S16_LE); 
	/* Two channels (stereo) */  snd_pcm_hw_params_set_channels(handle, params, 1); 
	/* 44100 bits/second sampling rate (CD quality) */ 
	val = 8000; 
	snd_pcm_hw_params_set_rate_near(handle,params, &val, &dir);  /* Set period size to 32 frames. */ 
	frames = 160; 
	snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
	/* Write the parameters to the driver */
	rc = snd_pcm_hw_params(handle, params);
	if (rc < 0) 
	{   
		fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));   
		exit(1); 
	}
	
	printf("%s: 777777777\n", __FUNCTION__);	
	/*Use a buffer large enough to hold one period*/
	snd_pcm_hw_params_get_period_size(params, &frames,  &dir); 
	size = frames * 2;
	/* 2 bytes/sample, 2 channels */ 
	buffer = (char *) malloc(size); 
	/* We want to loop for 5 seconds */
	snd_pcm_hw_params_get_period_time(params, &val, &dir); 
	/* 5 seconds in microseconds divided by   * period time */
	//loops = 5000000 / val;
	//while (loops > 0) {  
	printf("%s: 99999999\n", __FUNCTION__);	
	#endif
	
	
	#if SOUND_OSS
	printf("%s: aaaaaa\n", __FUNCTION__);		
    //打开声卡播放
    if(devplayfd == 0)
     if(OpenSnd(AUDIODSP1) <= 0)
      {
       printf("Open play sound device error!\n");
       //AudioPlayIsStart = 0;
       return;
      }


	printf("%s: cccccc\n", __FUNCTION__);	
    SetFormat(AUDIODSP1, FMT16BITS, FMT8K, 1);    //放音 STERO, WAVOUTDEV
	#endif
	printf("%s: eeeeeeeeee\n", __FUNCTION__);		
  	while(1)
  	{
		//printf("%s: 0000000\n", __FUNCTION__);	  	
		printf(".");
		//loops--;  
		//   rc = read(0, buffer, size); 
		rc = recvfrom (fd, &cbits[0], 38, 0,(struct sockaddr*)&addr, &len);

		//printf("rc=%d", rc);

		if (rc == 0) 
		{   
			fprintf(stderr, "end of file on input\n");    
			break;   
		}
		else if (rc != 38) 
		{     
			fprintf(stderr, "short read: read %d bytes\n", rc);
		}
		else
		{
			//printf("recv%d bytes \n", rc);		
		}   

		/*Read the "packet" encoded by sampleenc*/
		//fread(cbits, 1, nbBytes, fin[0]);

		/*Copy the data into the bit-stream struct*/
		speex_bits_read_from(&bits, cbits, 38);

		/*Decode the data*/
		speex_decode(state, &bits, output);

		/*Copy from float to short (16 bits) for output*/
		for (i=0;i<FRAME_SIZE;i++)
			out[i]=output[i];

		#if SOUND_ALSA
		rc = snd_pcm_writei(handle, out, frames);   
		if (rc == -EPIPE) 
		{    
			/* EPIPE means underrun */  
			fprintf(stderr, "underrun occurred\n");   
			snd_pcm_prepare(handle); 
		}
		else if (rc < 0) 
		{     
			fprintf(stderr, "error from writei: %s\n",   snd_strerror(rc));  
		} 
		else if (rc != (int)frames) 
		{    
			fprintf(stderr, "short write, write %d frames\n", rc); 
		}
		#endif
		
		#if SOUND_OSS
		if(devplayfd > 0)
		{
			rc = write(devplayfd, out, 320);
			printf("write soundcard %dByte\n", rc);
		}
		#endif
	} 
	
	#if SOUND_ALSA
	snd_pcm_drain(handle);
	snd_pcm_close(handle);
	#endif
	free(buffer); 
	return 0;
}

